﻿using Authority.DataTransferObject.MenuAuthority;
using Authority.DataTransferObject.Role;
using Authority.DataTransferObject.User;
using Authority.Doamin;
using Authority.Doamin.IRepository;
using Authority.Doamin.View;
using Authority.EFRepositoryImpl;
using Authority.IServices;
using Authority.IServices.Model.User;
using AutoMapper;
using HelperFromTheSkeleton.Convert;
using HelperFromTheSkeleton.Enums;
using HelperFromTheSkeleton.ExtendMethod;
using HelperFromTheSkeleton.Model.PageModel;
using System.Linq.Expressions;
using System.Reflection.PortableExecutable;

namespace Authority.ServiceImpl
{
    /// <summary>
    /// 用户权限服务
    /// </summary>
    public class UserServiceImpl : IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IUserRoleAuthorityRepository _userRoleRepository;
        private readonly IRoleAuthorityRepository _roleAuthorityRepository;
        private readonly IUnitWork _unitWork;
        private readonly IMapper _mapper;

        public UserServiceImpl(IUnitWork unitWork, IMapper mapper, IUserRepository userRepository, IUserRoleAuthorityRepository userRoleRepository,
            IRoleAuthorityRepository roleAuthorityRepository)
        {
            _userRepository = userRepository;
            _roleAuthorityRepository = roleAuthorityRepository;
            _unitWork = unitWork;
            _mapper = mapper;
            _userRoleRepository = userRoleRepository;
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<Guid> AddAsync(AddUserModel model)
        {
            if (string.IsNullOrEmpty(model.AccountNumber)) throw new InvalidOperationException("账号不能为空");
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("用户名称不能为空");
            if (string.IsNullOrWhiteSpace(model.Password)) throw new InvalidOperationException("密码不能为空");
            if (await _userRepository.CountAsync(m => m.AccountNumber == model.AccountNumber) > 0) throw new InvalidOperationException("账号重复");
            User dbInfo = new();
            model.CopyProperty(dbInfo);
            dbInfo.ID = Guid.NewGuid();
            _unitWork.Add(dbInfo);
            if (model.RoleIDs.Count > 0)
            {
                foreach (var roleID in model.RoleIDs)
                {
                    UserRoleAuthority userRole = new()
                    {
                        RoleAuthorityID = roleID,
                        UserID = dbInfo.ID
                    };
                    _unitWork.Add(userRole);
                }
            }
            await _unitWork.CommitAsync();
            return dbInfo.ID;
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task EditAsync(EditUserModel model)
        {
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("用户名称不能为空");
            if (model.ID == Guid.Empty) throw new InvalidOperationException("ID不能为空");
            User dbInfo = await _userRepository.FirstAsync(m => m.ID == model.ID) ?? throw new InvalidOperationException("找不到此用户");
            model.CopyProperty(dbInfo);
            _unitWork.Updata(dbInfo);
            List<UserRoleAuthority> userRole = await _userRoleRepository.FindAsync(m => m.UserID == model.ID, null);
            userRole.ForEach(m => _unitWork.Delete(m));
            if (model.RoleIDs.Count > 0)
            {
                foreach (var roleID in model.RoleIDs)
                {
                    UserRoleAuthority newUserRole = new()
                    {
                        RoleAuthorityID = roleID,
                        UserID = dbInfo.ID
                    };
                    _unitWork.Add(newUserRole);
                }
            }
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 通过角色Code为新增用户角色
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public async Task AddUserRoleByRoleCodeAsync(List<Guid> userIDs, List<string> codes)
        {
            if (userIDs.Count <= 0 || codes.Count <= 0) throw new InvalidOperationException("用户或角色code为空");
            if (await _userRepository.CountAsync(m => userIDs.Contains(m.ID)) != userIDs.Count())
            {
                throw new InvalidOperationException("用户选择有误");
            }
            var roleAuthorityEntitys = await _roleAuthorityRepository.FindAsync(m => codes.Contains(m.Code), null);
            if (roleAuthorityEntitys.Count != codes.Count())
            {
                throw new InvalidOperationException("角色code有误，请联系管理员检查角色code是否存在");
            }
            var roleIDs = roleAuthorityEntitys.Select(m => m.ID).ToList();
            var userRoles = await _userRoleRepository.FindAsync(m => roleIDs.Contains(m.RoleAuthorityID) && userIDs.Contains(m.UserID), null);
            foreach (var userID in userIDs)
            {
                foreach (var roleID in roleIDs)
                {
                    if (userRoles.FirstOrDefault(m => m.UserID == userID && m.RoleAuthorityID == roleID) == null)
                    {
                        var newUserRole = new UserRoleAuthority
                        {
                            UserID = userID,
                            RoleAuthorityID = roleID,
                        };
                        _unitWork.Add(newUserRole);
                    }
                }
            }
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 通过角色Code为删除用户角色
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public async Task DeleteUserRoleByRoleCodeAsync(List<Guid> userIDs, List<string> codes)
        {
            if (userIDs.Count <= 0 || codes.Count <= 0) throw new InvalidOperationException("用户或角色code为空");
            if (await _userRepository.CountAsync(m => userIDs.Contains(m.ID)) != userIDs.Count())
            {
                throw new InvalidOperationException("用户选择有误");
            }
            var roleAuthorityEntitys = await _roleAuthorityRepository.FindAsync(m => codes.Contains(m.Code), null);
            if (roleAuthorityEntitys.Count != codes.Count())
            {
                throw new InvalidOperationException("角色code有误，请联系管理员检查角色code是否存在");
            }
            var roleIDs = roleAuthorityEntitys.Select(m => m.ID).ToList();
            var userRoles = await _userRoleRepository.FindAsync(m => roleIDs.Contains(m.RoleAuthorityID) && userIDs.Contains(m.UserID), null);
            foreach (var userID in userIDs)
            {
                foreach (var roleID in roleIDs)
                {
                    var userRole = userRoles.FirstOrDefault(m => m.UserID == userID && m.RoleAuthorityID == roleID);
                    if (userRole != null)
                    {
                        _unitWork.Delete(userRole);
                    }
                }
            }
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 密码认证
        /// </summary>
        /// <returns></returns>
        public async Task<UserListDTO> PasswordAertificationAsync(string accountNumber, string password)
        {
            var user = await _userRepository.FirstAsync(m => m.AccountNumber == accountNumber) ?? throw new InvalidOperationException("账号不正确");
            if (user.Password != password) throw new InvalidOperationException("密码不正确");
            var result = _mapper.Map<UserListDTO>(user);
            return result;
        }

        /// <summary>
        /// 获取用户功能信息
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="subsystemID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserActionInfoDTO> GetUserActionAsync(Guid userID, Guid subsystemID)
        {
            UserActionInfoView view = (await _userRepository.FindUserActionInfoViewAsync(m => m.ID == userID, m => m.SubsystemID == subsystemID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserActionInfoDTO>(view);
            return result;
        }

        /// <summary>
        /// 获取用户菜单树
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="subsystemID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserMenuTreeDTO> GetUserMenuTreeAsync(Guid userID, Guid subsystemID)
        {
            UserMenuInfoView view = (await _userRepository.FindUserMenuInfoViewAsync(m => m.ID == userID, m => m.SubsystemID == subsystemID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserMenuTreeDTO>(view);
            var a = TreeConvert.EntityToTreeList<MenuTreeDTO, MenuView>(view.MenuInfos);
            return result;
        }

        /// <summary>
        /// 获取用户菜单列表
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="subsystemID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserMenuListDTO> GetUserMenuListAsync(Guid userID, Guid subsystemID)
        {
            UserMenuInfoView view = (await _userRepository.FindUserMenuInfoViewAsync(m => m.ID == userID, m => m.SubsystemID == subsystemID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserMenuListDTO>(view);
            return result;
        }

        /// <summary>
        /// 获取用户路由树
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="subsystemID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserRoutingTreeDTO> GetUserRoutingTreeAsync(Guid userID, Guid subsystemID)
        {
            UserRoutingView view = (await _userRepository.FindUserRoutingViewAsync(m => m.ID == userID, m => m.SubsystemID == subsystemID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserRoutingTreeDTO>(view);
            return result;
        }

        /// <summary>
        /// 获取用户路列表
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="subsystemID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserRoutingListDTO> GetUserRoutingListAsync(Guid userID, Guid subsystemID)
        {
            UserRoutingView view = (await _userRepository.FindUserRoutingViewAsync(m => m.ID == userID, m => m.SubsystemID == subsystemID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserRoutingListDTO>(view);
            return result;
        }

        /// <summary>
        /// 获取用户角色列表
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<UserRoleListDTO> GetUserRoleListAsync(Guid userID)
        {
            UserRoleInfoView dbInfo = (await _userRepository.FindUserRoleInfoViewAsync(m => m.ID == userID)).FirstOrDefault() ?? throw new InvalidOperationException("找不到用户信息");
            var result = _mapper.Map<UserRoleListDTO>(dbInfo);
            return result;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task DeleteAsync(Guid id)
        {
            var dbInfo = await _userRepository.FirstAsync(m => m.ID == id) ?? throw new InvalidOperationException("找不到此用户");
            _unitWork.Delete(dbInfo);
            List<UserRoleAuthority> userRole = await _userRoleRepository.FindAsync(m => m.UserID == id, null);
            userRole.ForEach(m => _unitWork.Delete(m));
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<UserListDTO>> GetAsync(Guid[] ids)
        {
            var dbInfos = await _userRepository.FindAsync(m => ids.Contains(m.ID), null);
            var result = _mapper.Map<List<UserListDTO>>(dbInfos);
            return result;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<(List<UserListDTO>, PageResultModel)> QueryAsync(QueryUserModel model)
        {
            Expression<Func<User, bool>> expression = m => true;
            if (!string.IsNullOrWhiteSpace(model.Name)) expression = expression.And(m => m.Name == model.Name);
            if (!string.IsNullOrWhiteSpace(model.AccountNumber)) expression = expression.And(m => m.AccountNumber == model.AccountNumber);
            (List<User> dbInfos, PageResultModel page) = await _userRepository.PageFindAsync(model, expression, m => m.Name, OrderByEnum.Asc);
            var result = _mapper.Map<List<UserListDTO>>(dbInfos);
            return (result, page);
        }
    }
}